package com.google.code.jtasks.model;

import org.joda.time.DateTime;
import org.joda.time.Duration;

import com.google.code.jtasks.model.IMappedTask.ITaskComment;

/**
 * An abstract representation of a work/time log entry against a task.
 */
public interface ITaskWorkEntry
{
	/**
	 * Returns the repository-specific ID of the person or organization that completed the work represented by
	 * this {@link ITaskWorkEntry}.
	 * 
	 * @return the repository-specific ID of the person or organization that completed the work represented by
	 *         this {@link ITaskWorkEntry}
	 */
	public String getWorker();

	/**
	 * Returns the {@link DateTime} representing when this {@link ITaskWorkEntry} was logged.
	 * 
	 * @return the {@link DateTime} representing when this {@link ITaskWorkEntry} was logged
	 */
	public DateTime getCreationTime();

	/**
	 * Returns a {@link Duration} representing the length of work represented by this {@link ITaskWorkEntry}.
	 * 
	 * @return a {@link Duration} representing the length of work represented by this {@link ITaskWorkEntry}
	 */
	public Duration getTimeWorked();

	/**
	 * Returns a reference to the ITaskComment that is associated with this {@link ITaskWorkEntry}, or
	 * <code>null</code> if there is none.
	 * 
	 * @return a reference to the ITaskComment that is associated with this {@link ITaskWorkEntry}, or
	 *         <code>null</code> if there is none
	 */
	public ITaskComment getAssociatedComment();

	/**
	 * Enumerates the {@link ITaskWorkEntry} {@link ITaskProperty}s.
	 */
	public static enum WorkEntryField implements ITaskProperty<ITaskWorkEntry>
	{
		/**
		 * Corresponds to {@link ITaskWorkEntry#getWorker()}.
		 */
		WORKER(String.class, false)
		{
			/**
			 * @see com.google.code.jtasks.model.ITaskWorkEntry.WorkEntryField#getValue(com.google.code.jtasks.model.ITaskWorkEntry)
			 */
			@Override
			public String getValue(ITaskWorkEntry owner) throws UnsupportedTaskPropertyException
			{
				return owner.getWorker();
			}
		},

		/**
		 * Corresponds to {@link ITaskWorkEntry#getCreationTime()}.
		 */
		CREATION_TIME(DateTime.class, false)
		{
			/**
			 * @see com.google.code.jtasks.model.ITaskWorkEntry.WorkEntryField#getValue(com.google.code.jtasks.model.ITaskWorkEntry)
			 */
			@Override
			public DateTime getValue(ITaskWorkEntry owner) throws UnsupportedTaskPropertyException
			{
				return owner.getCreationTime();
			}
		},

		/**
		 * Corresponds to {@link ITaskWorkEntry#getTimeWorked()}.
		 */
		TIME_WORKED(Duration.class, false)
		{
			/**
			 * @see com.google.code.jtasks.model.ITaskWorkEntry.WorkEntryField#getValue(com.google.code.jtasks.model.ITaskWorkEntry)
			 */
			@Override
			public Duration getValue(ITaskWorkEntry owner) throws UnsupportedTaskPropertyException
			{
				return owner.getTimeWorked();
			}
		},

		/**
		 * Corresponds to {@link ITaskWorkEntry#getAssociatedComment()}.
		 */
		ASSOCIATED_COMMENT(ITaskComment.class, false)
		{
			/**
			 * @see com.google.code.jtasks.model.ITaskWorkEntry.WorkEntryField#getValue(com.google.code.jtasks.model.ITaskWorkEntry)
			 */
			@Override
			public ITaskComment getValue(ITaskWorkEntry owner) throws UnsupportedTaskPropertyException
			{
				return owner.getAssociatedComment();
			}
		};

		private final Class<?> valueType;
		private final boolean optional;

		/**
		 * Constructs a new {@link WorkEntryField} instance.
		 * 
		 * @param valueType
		 *            the {@link Class} of value stored in this {@link WorkEntryField} in
		 *            {@link ITaskWorkEntry}
		 * @param optional
		 *            the {@link #isOptional()} value for the {@link WorkEntryField}
		 */
		private WorkEntryField(Class<?> valueType, boolean optional)
		{
			this.valueType = valueType;
			this.optional = optional;
		}

		/**
		 * @see com.google.code.jtasks.model.ITaskProperty#getName()
		 */
		@Override
		public String getName()
		{
			return name();
		}

		/**
		 * @see com.google.code.jtasks.model.ITaskProperty#isOptional()
		 */
		@Override
		public boolean isOptional()
		{
			return optional;
		}

		/**
		 * @see com.google.code.jtasks.model.ITaskProperty#getValueType()
		 */
		@Override
		public Class<? extends Object> getValueType()
		{
			return valueType;
		}

		/**
		 * @see com.google.code.jtasks.model.ITaskProperty#getValue(java.lang.Object)
		 */
		@Override
		public abstract Object getValue(ITaskWorkEntry owner) throws UnsupportedTaskPropertyException;
	}
}